/* Copyright (c) 2021 OceanBase and/or its affiliates. All rights reserved.
miniob is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
         http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details. */

//
// Created by WangYunlai on 2022/12/30.
//

#include "sql/operator/join_physical_operator.h"
#include "common/log/log.h"
#include "sql/expr/tuple.h"
#include <memory>

NestedLoopJoinPhysicalOperator::NestedLoopJoinPhysicalOperator() {}

RC NestedLoopJoinPhysicalOperator::open(Trx *trx)
{
  if (children_.size() <= 1) {
    // 如果需要join的表的个数小于等于1，那就说明有问题，不需要join
    // 只有两个及以上的表才需要join
    LOG_WARN("nlj operator should have more than 2 children");
    return RC::INTERNAL;
  }
  LOG_DEBUG("Now we have %d children.", children_.size());
  index           = 1;
  right_has_empty = 0;
  RC rc           = RC::SUCCESS;
  left_           = children_[0].get();
  // right_        = children_[1].get();

  // 每次调用要清空
  to_join_tables_.clear();
  round_done_.clear();
  right_closed_.clear();

  for (unsigned i = 0; i < children_.size(); i++) {
    to_join_tables_.push_back(children_[i].get());
  }

  // round_done_   = true;
  for (unsigned i = 0; i < children_.size(); i++) {
    round_done_.push_back(true);
  }

  // right_closed_ = true;
  for (unsigned i = 0; i < children_.size(); i++) {
    right_closed_.push_back(true);
  }

  rc   = left_->open(trx);
  trx_ = trx;
  return rc;
}

RC NestedLoopJoinPhysicalOperator::next()
{
  bool left_need_step = (left_tuple_ == nullptr);
  RC   rc             = RC::SUCCESS;
  bool all_round_done = true;
  for (unsigned i = 1; i < round_done_.size(); i++) {
    all_round_done = all_round_done && round_done_[i];
  }
  if (all_round_done) {  // 如果右边所有的表都枚举完了，说明左边需要下一步
    left_need_step = true;
  } else {  // 否则就只需要将右边的表组合出来下一个元组
    rc = right_next();
    if (rc != RC::SUCCESS) {
      if (rc == RC::RECORD_EOF) {
        left_need_step = true;
      } else {
        return rc;
      }
    } else {
      return rc;  // got one tuple from right
    }
  }

  RC rc1;
  if (left_need_step) {
    rc1 = left_next();
    if (rc1 != RC::SUCCESS) {
      return rc1;
    }
  }

  rc = right_next();  // 右边回到初始态
  if (rc != RC::SUCCESS) {
    // 应该先把left都遍历完成
    if (rc1 != RC::RECORD_EOF) {
      while (RC::SUCCESS == (rc1 = to_join_tables_[0]->next())) {}
    }
  }
  return rc;
}

RC NestedLoopJoinPhysicalOperator::close()
{
  RC rc = left_->close();
  if (rc != RC::SUCCESS) {
    LOG_WARN("failed to close left oper. rc=%s", strrc(rc));
  }

  for (unsigned i = 1; i < right_closed_.size(); i++) {
    if (!right_closed_[i]) {
      rc = to_join_tables_[i]->close();
      if (rc != RC::SUCCESS) {
        LOG_WARN("failed to close right oper. rc=%s", strrc(rc));
      } else {
        right_closed_[i] = true;
      }
    }
  }
  return rc;
}

Tuple *NestedLoopJoinPhysicalOperator::current_tuple() { return &joined_tuple_; }

RC NestedLoopJoinPhysicalOperator::left_next()
{
  RC rc = RC::SUCCESS;
  rc    = left_->next();
  if (rc != RC::SUCCESS) {
    return rc;
  }

  left_tuple_ = left_->current_tuple();
  joined_tuple_.set_left(left_tuple_);
  return rc;
}

RC NestedLoopJoinPhysicalOperator::right_next()
{
  RC rc = RC::SUCCESS;
  // 还没做数量检查
  if (right_has_empty == 0) {
    right_has_empty = 2;
    for (unsigned i = 1; i < to_join_tables_.size(); i++) {
      rc = to_join_tables_[i]->open(trx_);
      if (rc != RC::SUCCESS) {
        LOG_WARN("Open join table failed.");
        return rc;
      }
      int num = 0;
      while (to_join_tables_[i]->next() != RC::RECORD_EOF) {
        num++;
      }
      to_join_tables_[i]->close();
      if (num == 0) {
        right_has_empty = 1;
        break;
      }
    }
  }
  if (right_has_empty == 1) {
    return RC::RECORD_EOF;
  }
  // 检查是否全部遍历完成了
  bool all_round_done = true;
  for (unsigned i = 1; i < round_done_.size(); i++) {
    all_round_done = all_round_done && round_done_[i];
  }
  // 如果全部遍历完成了，先关闭掉没有关闭的表
  if (all_round_done) {
    for (unsigned i = 1; i < right_closed_.size(); i++) {
      if (!right_closed_[i]) {
        rc               = to_join_tables_[i]->close();
        right_closed_[i] = true;
        if (rc != RC::SUCCESS) {
          return rc;
        }
      }
    }
    // 如果右边已经全部遍历完了一轮，那么就关闭后重新开启一轮
    for (unsigned i = 1; i < to_join_tables_.size(); i++) {
      rc = to_join_tables_[i]->open(trx_);
      if (rc != RC::SUCCESS) {
        LOG_WARN("Open join table failed.");
        return rc;
      }
      if (i > 1) {
        rc = to_join_tables_[i]->next();
      }
      if (rc != RC::SUCCESS) {
        // 这里表明前边的表没有问题，但是后边的表出现了问题了
        // 这里需要把所有的表全部关闭掉
        unsigned j = 1;
        for (; j < i; j++) {
          while (to_join_tables_[j]->next() != RC::RECORD_EOF)
            ;
          to_join_tables_[j]->close();
          right_closed_[i] = true;
          round_done_[i]   = true;
        }
        to_join_tables_[i]->close();
        return RC::RECORD_EOF;
      }
      right_closed_[i] = false;
      round_done_[i]   = false;
    }
  }

  // 首先让其next
  unsigned cnt = 0;
  for (unsigned i = 1; i <= index; i++) {
    rc = to_join_tables_[i]->next();
    if (rc == RC::SUCCESS) {
      break;
    } else if (rc == RC::RECORD_EOF) {
      cnt++;
      if (i == index) {
        index++;
        while (index < to_join_tables_.size() && to_join_tables_[index]->next() == RC::RECORD_EOF) {
          cnt++;
          index++;
        }
        break;
      }
    } else {
      return rc;
    }
  }
  // 这时候说明已经遍历结束了
  if (index >= to_join_tables_.size()) {
    for (unsigned i = 1; i < to_join_tables_.size(); i++) {
      round_done_[i] = true;
      if (!right_closed_[i]) {
        to_join_tables_[i]->close();
        right_closed_[i] = true;
      }
    }
    index = 1;
    return RC::RECORD_EOF;
  }
  // 这时候没有遍历结束，还需要next
  else {
    // 如果没有遍历完，就需要把cnt个EOF的表关闭然后重新打开
    for (unsigned i = 1; i <= cnt; i++) {
      to_join_tables_[i]->close();
      to_join_tables_[i]->open(trx_);
      to_join_tables_[i]->next();
    }
  }
  /////

  for (unsigned i = 1; i < to_join_tables_.size(); i++) {
    to_join_tuples_.push_back(to_join_tables_[i]->current_tuple());
    // 下边的代码调试用
    // Value v;
    // Tuple *tmp = to_join_tables_[i]->current_tuple();
    // tmp->cell_at(0, v);
    // tmp->cell_at(1, v);
  }

  // 下面就是得到了对这些元组的一些处理
  if (to_join_tuples_.size() == 1) {
    joined_tuple_.set_right(to_join_tuples_[0]);
    to_join_tuples_.clear();
    return RC::SUCCESS;
  }
  for (unsigned i = 1; i <= to_join_tuples_.size(); i++) {
    JoinedTuple jt;
    join_tuple_list.push_back(jt);
  }
  unsigned i = 0;
  while (to_join_tuples_.size() > 1) {

    Tuple *t2 = to_join_tuples_.back();
    to_join_tuples_.pop_back();
    Tuple *t1 = to_join_tuples_.back();
    to_join_tuples_.pop_back();
    join_tuple_list[i].set_left(t1);
    join_tuple_list[i].set_right(t2);
    to_join_tuples_.push_back(&join_tuple_list[i]);
    i++;
  }

  // 最后 to_join_tuples只剩下了一个元素
  joined_tuple_.set_right(to_join_tuples_[0]);
  // 最后不要忘记要clear掉to_join_tuples
  to_join_tuples_.clear();
  return RC::SUCCESS;
}

// next是不是带头指针的链表呢
